﻿using MySql.Data.MySqlClient;
using MySqlX.XDevAPI.Common;
using NewChillers.Helpers;
using NewChillers.Models;
using NewChillers.Models.Events;
using NewChillers.Utils;
using NewChillers.Views;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace NewChillers.ViewModels
{
    public class ShellViewModel : ObservableObject
    {
        #region 枚举
        public enum CommState
        {
            Connected,      // 通讯 已连接
            Disconnected    // 通讯 未连接
        }
        #endregion

        private UserModel _currentUser; // 当前登录用户
        private string _maximizeIconPath; // 最大化按钮的图标路径
        private UIElement _mainContent; // 主要内容区域 显示的页面 UserControl 也可以
        public event EventHandler<UserInfoUpdateEventArgs> UserInfoUpdate; // 静态事件
        private CommState _currentCommState; // 当前通讯连接状态

        #region 字典 - 页面切换用
        // 缓存字典：用于存储需要缓存的页面实例
        private readonly Dictionary<string, UIElement> _cachedPages = new();

        // 页面工厂注册表 全部单例模式下可以简化为：
        // 传值：当前登录用户的信息 此页面(用于实例化事件)
        private readonly Dictionary<string, Func<UserModel, ShellViewModel, UIElement>> _pageFactories = new()
        {
            { "Home", (user, shellVm) => new HomePage(user, shellVm) }, // 主页面 仪表盘页面 user 只是参数 委托是个模板 没有实际调用
            { "ManualControl", (user, shellVm) => new ManualControlPage(user, shellVm) }, // 手动页面
            { "Recipe", (user, shellVm) => new RecipePage(user, shellVm) }, // 配方页面
            { "Communication", (user, shellVm) => new CommunicationPage(user, shellVm) }, // 通讯页面
            { "IO", (user, shellVm) => new IOPage(user, shellVm) }, // I/O页面
            { "Help", (user, shellVm) => new HelpDocPage() }, // 帮助文档页面
            { "User", (user, shellVm) => new UserPage(user, shellVm) }, // 用户页面
            { "Product", (user, shellVm) => new ProductPage(user, shellVm) }, // 产品页面
            { "Alarm", (user, shellVm) => new AlarmPage(user, shellVm) }, // 报警页面
            { "Log", (user, shellVm) => new LogPage(user, shellVm) }, // 日志页面
            //{ "Settings", (user, shellVm) => new SettingsPage() } // 设置页面
        };
        #endregion

        public CommState CurrentCommState
        {
            get => _currentCommState;
            set => SetProperty(ref _currentCommState, value);
        }

        public UIElement MainContent
        {
            get => _mainContent;
            set => SetProperty(ref _mainContent, value);
        }

        public string UserName
        {
            get => _currentUser.UserName;
            set { _currentUser.UserName = value; RaisePropertyChanged(); }
        }

        public int UserIdentity
        {
            get => _currentUser.UserIdentity;
            set
            {
                _currentUser.UserIdentity = value;
                RaisePropertyChanged();
                RaisePropertyChanged(nameof(RankName));
                RaisePropertyChanged(nameof(IsEmployee));
                RaisePropertyChanged(nameof(IsAdmin));
            }
        }

        public string RankName => _currentUser.RankName;
        // 计算属性 当前用户身份
        public bool IsEmployee => UserIdentity == 1; // 是员工
        public bool IsAdmin => UserIdentity == 2; // 是管理员

        // 计算属性 字母头像
        public string UserInitials => string.IsNullOrEmpty(UserName) ? "?" : new string(UserName.Split(' ').Select(s => s[0]).ToArray()).ToUpper();

        public string MaximizeIconPath
        {
            get => _maximizeIconPath;
            set => SetProperty(ref _maximizeIconPath, value);
        }

        public ICommand WindowMinCommand { get; } // 窗口最小化
        public ICommand WindowMaxCommand { get; } // 窗口最大化
        public ICommand ExitCommand { get; } // 退出程序
        public ICommand NavigateCommand { get; } // 页面切换
        public ICommand ChangePasswordCommand { get; } // 修改密码
        public ICommand LogoutCommand { get; } // 退出登录

        public ShellViewModel(UserModel user)
        {
            // 当前登录用户
            _currentUser = user;

            // 初始化命令对象
            WindowMinCommand = new RelayCommand(ExecuteWindowMin);
            WindowMaxCommand = new RelayCommand(ExecuteWindowMax);
            ExitCommand = new RelayCommand(ExecuteExit);
            NavigateCommand = new RelayCommand<string>(ExecuteNavigate); // 导航
            ChangePasswordCommand = new RelayCommand(ExecuteChangePassword); // 修改密码
            LogoutCommand = new RelayCommand(ExecuteLogout); // 退出登录

            // 测试用 -- 页面创建失败
            //_pageFactories["Home"] = (user, shellVm) =>
            //{
            //    throw new Exception();
            //};

            // 设置默认值
            UpdateMaximizeIcon(true); // 初始化"最大化"图标
            CurrentCommState = CommState.Disconnected;
            //CurrentCommState = CommState.Connected;

            // 订阅通讯状态变化事件 先订阅 再加载通讯页面 不然时机问题会导致第一次事件通知被触发时 订阅者没有订阅
            // 也体现了事件中心类的优势 不然直接在通讯页面声明事件的话 可能就无解了
            AppEventCenter.CommStateChange += OnCommStateChanged;

            // 预加载 除Home外 所有页面
            PreloadAllPages();

            NavigateToPageSingleton("Home"); // 设置默认页面 三选一

        }

        /// <summary>
        /// 事件处理方法
        /// </summary>
        private void OnCommStateChanged(object? sender, CommStateChangeEventArgs e)
        {
            //// 接收并处理事件数据
            //CurrentCommState = e.State;
            //// 根据状态更新UI或执行其他逻辑
            //Debug.WriteLine($"收到通讯状态变化: {e.State}");

            // 确保在主线程更新UI（如果是WPF）
            Application.Current?.Dispatcher.Invoke(() =>
            {
                CurrentCommState = e.State;
                Debug.WriteLine($"收到通讯状态变化: {e.State}");
                if (e.State == CommState.Connected)
                    LogHelper.Info(this.GetType(), "[通讯状态变化]|" + "连接成功", _currentUser.UserAccount);
                if (e.State == CommState.Disconnected)
                    LogHelper.Warn(this.GetType(), "[通讯状态变化]|" + "连接断开", _currentUser.UserAccount);
            });
        }
        /// <summary>
        /// 取消事件订阅
        /// </summary>
        public void Dispose()
        {
            AppEventCenter.CommStateChange -= OnCommStateChanged;
        }

        #region 用户菜单 - 修改密码
        private void ExecuteChangePassword(object obj)
        {
            try
            {
                // 创建对话框并传值
                var changePasswordView = new ChangePasswordView(_currentUser);

                // 设置Owner建立窗口关系
                changePasswordView.Owner = Application.Current.MainWindow;

                // 显示模态对话框并等待结果
                bool? result = changePasswordView.ShowDialog();

                // 处理对话框返回结果
                if (result == true)
                {
                    Debug.WriteLine("密码修改成功！");

                    // 修改密码后 更新用户信息 通过事件实现
                    // 通过当前用户ID 从数据库 获取新的用户信息
                    UserModel updatedUser = GetUserInfoById(_currentUser.UserAccount);
                    // 更新主窗口(自身) 用户信息
                    UpdateCurrentUser(updatedUser);
                    // 通知 其他页面
                    OnUserInfoUpdate(updatedUser);

                    LogHelper.Info(this.GetType(), "[修改密码]|" + "修改密码成功", _currentUser.UserAccount);
                }
                else if (result == false)
                {
                    // 用户取消了操作
                    Debug.WriteLine("用户取消了密码修改");
                }
            }
            catch (Exception ex)
            {
                MsgBoxHelper.Error($"打开修改密码窗口失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 通知 其他页面
        /// </summary>
        protected virtual void OnUserInfoUpdate(UserModel updatedUser)
        {
            UserInfoUpdate?.Invoke(this, new UserInfoUpdateEventArgs(updatedUser));
        }

        /// <summary>
        /// 更新主窗口(自身) 用户信息
        /// </summary>
        private void UpdateCurrentUser(UserModel updatedUser)
        {
            // 字段
            _currentUser = updatedUser;

            // 属性
            RaisePropertyChanged(nameof(UserName));
            RaisePropertyChanged(nameof(UserIdentity));
            RaisePropertyChanged(nameof(RankName));
            RaisePropertyChanged(nameof(IsAdmin));
            RaisePropertyChanged(nameof(IsEmployee));
            RaisePropertyChanged(nameof(UserInitials));
        }

        /// <summary>
        /// 从数据库获取用户信息 By 用户ID
        /// </summary>
        private UserModel GetUserInfoById(string currentUserAccount)
        {
            // SELECT * FROM user_info WHERE user_account = "1"
            string sql = "SELECT * FROM user_info WHERE user_account = @UserAccount";

            var parameters = new MySqlParameter[]
            {
                new MySqlParameter("@UserAccount", currentUserAccount)
            };

            Func<IDataRecord, UserModel> mapper = reader => new UserModel
            {
                UserAccount = reader["user_account"].ToString(),
                UserName = reader["user_name"].ToString(),
                UserPassword = reader["user_password"].ToString(),
                UserIdentity = Convert.ToInt32(reader["user_identity"])
            };

            var result = MysqlHelper.ExecuteQuery(sql, mapper, parameters);

            return result.FirstOrDefault();
        }
        #endregion

        #region 用户菜单 - 退出登录
        /// <summary>
        /// 退出登录 后续需要检查是否正在生产中
        /// </summary>
        private void ExecuteLogout(object obj)
        {
            // 检查是否正在生产中（根据您的业务逻辑）
            if (IsProductionRunning())
            {
                MsgBoxHelper.Warning("当前正在生产中，无法退出登录");
                return;
            }

            // 确认退出登录
            if (MsgBoxHelper.ConfirmYesNo("确定要退出登录吗？"))
            {
                Logout();
            }
        }

        /// <summary>
        /// 实际的退出登录逻辑
        /// </summary>
        private void Logout()
        {
            try
            {
                UserInfoUpdate = null; // 清空所有订阅者
                Dispose(); // 通讯状态事件订阅

                // 2. 清理页面缓存 先清理这个
                ClearPageCache(true);

                // 1. 清理当前用户数据
                _currentUser = new UserModel();

                // 3. 重置UI状态
                RaisePropertyChanged(nameof(UserName));
                RaisePropertyChanged(nameof(UserIdentity));
                RaisePropertyChanged(nameof(RankName));
                RaisePropertyChanged(nameof(IsAdmin));
                RaisePropertyChanged(nameof(IsEmployee));
                RaisePropertyChanged(nameof(UserInitials));

                // 4. 显示登录窗口
                ShowLoginWindow();

                // 5. 关闭当前主窗口
                CloseMainWindow();
            }
            catch (Exception ex)
            {
                MsgBoxHelper.Error($"退出登录失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 关闭主窗口的方法
        /// </summary>
        private void CloseMainWindow()
        {
            // 查找并关闭主窗口
            foreach (Window window in Application.Current.Windows)
            {
                if (window is ShellView || window.Title == "清大天达|制冷机高精度自动充排气台") // 根据你的实际窗口类名或标题调整
                {
                    window.Close();
                    break;
                }
            }
        }

        /// <summary>
        /// 显示登录窗口的方法
        /// </summary>
        private void ShowLoginWindow()
        {
            try
            {
                LoginView loginView = new LoginView();
                loginView.Show();
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"创建登录窗口失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 检查是否正在生产中的方法
        /// </summary>
        private bool IsProductionRunning()
        {
            // 这里需要根据您的业务逻辑来判断
            // 例如：检查是否有正在运行的任务、设备状态等
            return false; // 暂时返回false，您需要根据实际情况实现
        }
        #endregion

        #region 导航命令执行 单例模式
        /// <summary>
        /// 导航命令执行
        /// </summary>
        private void ExecuteNavigate(object parameter)
        {
            if (parameter is string pageKey)
            {
                // 全部使用单例
                NavigateToPageSingleton(pageKey);

            }
        }

        // 全部单例（使用Singleton_前缀版本）
        private void NavigateToPageSingleton(string pageKey)
        {
            // 先检查请求的页面是否配置
            if (!_pageFactories.ContainsKey(pageKey))
            {
                // 如果页面未配置，使用默认页面Home
                Debug.WriteLine($"警告: 页面 {pageKey} 未配置，导航至默认页面 Home");
                pageKey = "Home"; // 直接使用硬编码的默认值
            }

            // 获取单例页面实例并设置为主内容
            MainContent = GetOrCreateSingletonPage(pageKey);
        }

        /// <summary>
        /// 获取或创建单例页面 - 统一的单例获取方法
        /// </summary>
        private UIElement GetOrCreateSingletonPage(string pageKey, bool hasFallback = false)
        {
            // 为每个单例页面使用固定的键名
            string singletonKey = $"Singleton_{pageKey}";

            // 存在则返回
            if (_cachedPages.TryGetValue(singletonKey, out var singletonPage))
            {
                Debug.WriteLine($"使用单例实例: {pageKey}");
                return singletonPage;
            }

            try
            {
                // 创建新实例
                Debug.WriteLine($"创建单例: {pageKey}");
                var newPage = _pageFactories[pageKey](_currentUser, this); // 直接调用方法 因为前面已经验证过 传值 _currentUser已赋值
                _cachedPages[singletonKey] = newPage;
                return newPage;
            }
            catch (Exception ex)
            {
                // 只允许一次fallback 防止递归
                //if (!hasFallback && pageKey != "Home")
                //{
                //    Debug.WriteLine($"Fallback到Home页面");
                //    return GetOrCreateSingletonPage("Home", true);
                //}
                if (pageKey == "Alarm")
                    throw;
                Debug.WriteLine($"创建页面 {pageKey} 失败: {ex.Message}");
                MsgBoxHelper.Error($"创建页面 {pageKey} 失败，请尝试重启应用程序。\n错误详情: {ex.Message}");
                LogHelper.Error(this.GetType(), "[创建页面]|" + $"创建页面 {pageKey} 失败", ex, _currentUser.UserAccount);
                return CreateErrorPage($"创建页面 {pageKey} 失败，请尝试重启应用程序。");
            }
        }

        /// <summary>
        /// 最终错误处理
        /// </summary>
        private UIElement CreateErrorPage(string errorText)
        {
            return new TextBlock
            {
                Text = errorText,
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center,
                Foreground = Brushes.Black,
                FontSize = 36
            };
        }

        /// <summary>
        /// 清理页面缓存
        /// </summary>
        public void ClearPageCache(bool clearAll = true, string specificPage = null)
        {
            if (clearAll)
            {
                _cachedPages.Clear();
                Debug.WriteLine("所有页面缓存已清理");
            }
            else if (specificPage != null && _pageFactories.ContainsKey(specificPage))
            {
                var keyToRemove = $"Singleton_{specificPage}";
                _cachedPages.Remove(keyToRemove);
                Debug.WriteLine($"页面 {specificPage} 缓存已清理");
            }
        }

        /// <summary>
        /// 预加载所有页面
        /// </summary>
        private void PreloadAllPages()
        {
            try
            {
                Debug.WriteLine("开始预加载所有页面(排除Home页面)...");

                // 排除Home页面，只预加载其他页面
                var pagesToPreload = _pageFactories.Keys.Where(key => key != "Home").ToList();

                // 直接遍历 除Home页面外 所有页面键进行预加载
                foreach (var pageKey in pagesToPreload)
                {
                    try
                    {
                        // 调用现有的单例获取方法，会自动创建并缓存
                        GetOrCreateSingletonPage(pageKey);
                        Debug.WriteLine($"预加载页面 {pageKey} 成功");
                    }
                    catch (Exception ex)
                    {
                        // 单个页面加载失败不影响其他页面
                        Debug.WriteLine($"预加载页面 {pageKey} 失败: {ex.Message}");
                        if (pageKey == "Alarm")
                        {
                            // 显示错误对话框
                            Debug.WriteLine($"关键页面 Alarm(警报) 创建失败，程序无法安全启动: {ex.Message}");
                            MsgBoxHelper.Error("关键页面 Alarm(警报) 创建失败，程序无法安全启动，请检查报警系统");
                            LogHelper.Error(this.GetType(), "[创建页面]|" + "关键页面 Alarm(警报) 创建失败，程序无法安全启动，请检查报警系统", ex, _currentUser.UserAccount);

                            // 终止应用程序
                            Application.Current.Dispatcher.Invoke(() =>
                            {
                                Application.Current.Shutdown(1); // 非正常退出码
                            });
                            return; // 直接返回，不再继续预加载
                        }
                    }
                }

                Debug.WriteLine("所有页面预加载完成（Home页面无需预加载，而是直接加载）");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"预加载过程异常: {ex.Message}");
            }
        }

        #endregion

        #region 右上角 三个控制按钮
        /// <summary>
        /// 窗口最小化
        /// </summary>
        private void ExecuteWindowMin(object obj)
        {
            if (obj is Window window) // 类型转换
            {
                window.WindowState = WindowState.Minimized;
            }
        }

        /// <summary>
        /// 窗口最大化
        /// </summary>
        private void ExecuteWindowMax(object obj)
        {
            if (obj is Window window)
            {
                if (window.WindowState == WindowState.Maximized)
                {
                    // 如果已经是最大化，就还原
                    window.WindowState = WindowState.Normal;
                    UpdateMaximizeIcon(false); // 更新为最大化图标
                }
                else
                {
                    // 如果是正常状态，就最大化
                    window.WindowState = WindowState.Maximized;
                    UpdateMaximizeIcon(true); // 更新为还原图标
                }
            }
        }

        /// <summary>
        /// 窗口最大化，更新图标封装
        /// </summary>
        private void UpdateMaximizeIcon(bool isMaximized)
        {
            if (isMaximized)
            {
                // 已最大化时显示"还原"图标
                MaximizeIconPath = "pack://application:,,,/NewChillers;component/Images/收起文本域_collapse-text-input.svg";
            }
            else
            {
                // 未最大化时显示"最大化"图标
                MaximizeIconPath = "pack://application:,,,/NewChillers;component/Images/展开文本域_expand-text-input.svg";
            }
        }

        /// <summary>
        /// 退出程序
        /// </summary>
        private void ExecuteExit(object obj)
        {
            if (MsgBoxHelper.ConfirmYesNo("确定要退出程序吗？"))
                Application.Current.Shutdown();
        }
        #endregion


    }
}
